package BNS.coloring;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import BNS.graphs.GraphPack;
import BNS.plumbing.BNSGameController;
import BNS.plumbing.Library;


/** This is a utility for creating ColoringGames and saving them in files.
	It is intended to get all the details and opportunities for error done correctly
	so that there is no load on the supervisor's brain cells during a live session.
	*/
public class GameBuilder extends JFrame implements ActionListener {
	/**
   * 
   */
  private static final long serialVersionUID = 1L;
  private JTextField colorField, scrambleField, timeField, payField, fileField,
						preField, gameField, sufField, packField;
	//private JSlider colorSlide;
	//private JLabel gpLabel;
	private JButton submit;
	private String[] gpNames;
	private int gpNum=0;
	private JComboBox typeList;
	//private String prefix;
	
	public GameBuilder(String[] args) {
		gpNames= args;
		System.err.println("making "+ args.length +" games");

		String prep= System.getProperty("PREP");
		if (prep==null) prep= "./";
		Library.setPrep(new File(prep));
		/* We discover the value of the ARCH property, which will be used
		in the Library for storing session files and exp files. */
		String arch= System.getProperty("ARCH");
		if (arch==null) arch= "./output";
		Library.setArch(new File(arch));

		setTitle("BNS Game GameBuilder");
		setSize(500,190);
		JPanel panel= new JPanel();
		panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
		
		JPanel typePanel= new JPanel();
		typePanel.setLayout(new BoxLayout(typePanel, BoxLayout.X_AXIS));
		typePanel.add(new JLabel("game type:",JLabel.RIGHT));		
		String[] typeStrings= { "","Consensus", "Coloring", "VoterCon", 
								"Matching", "KingPawn", "MarketIS" };
		typeList= new JComboBox(typeStrings);
    typeList.setSelectedItem("Coloring");
		typeList.addActionListener(this);
		typePanel.add(typeList);
		panel.add(typePanel);		
		
		JPanel packPanel= new JPanel();
		packPanel.setLayout(new BoxLayout(packPanel, BoxLayout.X_AXIS));
		packPanel.add(new JLabel("pack file:",JLabel.RIGHT));		
		packField= new JTextField(); packPanel.add(packField);
		panel.add(packPanel);
		
		JPanel colorPanel= new JPanel();
		colorPanel.setLayout(new BoxLayout(colorPanel, BoxLayout.X_AXIS));
		colorPanel.add(new JLabel("number of colors:",JLabel.RIGHT));
		colorField= new JTextField(3); colorPanel.add(colorField);
    colorPanel.add(new JLabel("scramble colors:",JLabel.RIGHT));
    scrambleField= new JTextField("1",3); colorPanel.add(scrambleField);
		panel.add(colorPanel);
		
		JPanel payPanel= new JPanel();
		payPanel.setLayout(new BoxLayout(payPanel, BoxLayout.X_AXIS));
		payPanel.add(new JLabel("normal payoff:",JLabel.RIGHT));		
		//leanField= new JTextField("1.00",5); payPanel.add(leanField);
		payField= new JTextField(5); payPanel.add(payField);
    payPanel.add(new JLabel("bonus vector:",JLabel.RIGHT));    
    fileField= new JTextField(15); payPanel.add(fileField);
		panel.add(payPanel);
		
		JPanel timePanel= new JPanel();
		timePanel.setLayout(new BoxLayout(timePanel, BoxLayout.X_AXIS));
		timePanel.add(new JLabel("game time limit:",JLabel.RIGHT));		
		timeField= new JTextField("180",5); timePanel.add(timeField);
		panel.add(timePanel);
		
		JPanel gamePanel= new JPanel();
		gamePanel.setLayout(new BoxLayout(gamePanel, BoxLayout.X_AXIS));
		gamePanel.add(new JLabel("game file:",JLabel.RIGHT));
		preField= new JTextField(10); gamePanel.add( preField);preField.setText("CLR-");
		gameField=new JTextField(50); gamePanel.add(gameField);
		sufField= new JTextField(".game",10); gamePanel.add( sufField);
		panel.add(gamePanel);
		
		submit= new JButton("submit"); submit.addActionListener(this); panel.add(submit);
		getContentPane().add(panel);
		validate();	// ?
//		pack();
		setLocation(700,60);
		setVisible(true);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		nextPack();
		}
	
	private void nextPack() {
		if (gpNum < gpNames.length) {
			packField.setText(gpNames[gpNum]);
			String pack= new File(gpNames[gpNum]).getName();
	    //identField= new JTextField("0",20); payPanel.add(identField);
//			System.err.println("gpack suffix found at "+ pack.indexOf(".gpack"));
			int sufidx= pack.indexOf(".gpack");
			if (sufidx<1) sufidx= pack.length();
			String fname= pack.substring(0,sufidx);
			Pattern pattern = Pattern.compile("c=\\d*");
			Matcher matcher = pattern.matcher(fname);
			if (matcher.find()) {
				int st= matcher.start();
				int nd= matcher.end();
				String cpull= fname.substring(st+2,nd);
				int chroma= Integer.parseInt(cpull);
				//System.err.format("matched (%d,%d) found %s%n",st,nd,cpull);
				System.err.println("chromatic number found "+ chroma);
				if (chroma>2) colorField.setText(""+chroma);
				}
			gameField.setText(fname);
			}
		else if (gpNum == gpNames.length) {
			packField.setText("");
			gameField.setText("");
			}
		gpNum++;
		}
	
	private void makeAndSave() {
		File pfile= new File(packField.getText());
		System.err.println("obtaining gpack at "+ pfile);
		GraphPack gp= Library.getPack(pfile);
		if (gp==null) return;
		String type= (String)typeList.getSelectedItem();
		//float leanPay= Float.parseFloat(leanField.getText());
    int colors= Integer.parseInt(colorField.getText());
		float pay= Float.parseFloat(payField.getText());
		Vector<Float> bonus= parseBonusVector(fileField.getText(),colors);
		int scramble= Integer.parseInt(scrambleField.getText());
		int time= Integer.parseInt(timeField.getText());
		String prefix= preField.getText();
		String suffix= sufField.getText();
		String gfld= prefix + gameField.getText() + suffix;
		System.err.println(type +", params: "+ pay +", "+ time);
		BNSGameController game= null;
		if (type.equals("Coloring"))  game= new ColoringGame(gp,colors,time,pay,bonus,scramble); 
		if (type.equals("Consensus")) game= new ConsensusGame(gp,colors,time,pay);
		if (type.equals("VoterCon" )) {
			String fileName= fileField.getText();
			float[][] payoffs= readRaggedArray(new File(fileName));
			game= new VoterGame   (gp,colors,time, pay,payoffs);
			}
//		if (type.equals("Matching"))  game= new MatchingGame(gp,colors,time,phatPay);
//		if (type.equals("KingPawn"))  game= new KingPawnGame(gp,time,leanPay,phatPay);
//		if (type.equals("MarketIS"))  game= new MarketISGame(gp,time,leanPay,phatPay);
		if (game!=null) {
			System.err.println("game obtained: "+ game.getInfo());
			Library.putGame(new File(gfld),game);
			System.err.println("saved game at "+ gfld);
			}
		else System.err.println("FAILED to construct game ");
		}
	
	private Vector<Float> parseBonusVector(String s,int colors) {
	  String[] tokens=s.split(" ");
	  Vector<Float> bonus=new Vector<Float>();
	  /*for(int i=0;i<colors;i++) {
	    if(tokens.length>i) bonus.add(Float.parseFloat(tokens[i]);
	    else bonus.add(0);
	  }*/
	  System.err.println(tokens.length);
	  System.err.println(tokens[0].equals(""));
	  if(!tokens[0].equals(""))
  	  for(String current:tokens) {
  	    bonus.add(Float.parseFloat(current));
  	  }
	  return bonus;
	}
	
	/** mandated by ActionListener interface. Handles the game type menu and the submit button. */
	public void actionPerformed(ActionEvent e) { 
		Object src= e.getSource();
		if (src==submit) { makeAndSave(); nextPack(); }
		if (src==typeList) { 
			String type= (String)typeList.getSelectedItem();
			preField.setText("");
			if (type.equals("Coloring"))  preField.setText("CLR-");
			if (type.equals("Consensus")) preField.setText("CNS-");
			if (type.equals("VoterCon"))  preField.setText("VTR-");
//			if (type.equals("Matching"))  preField.setText("MCH-");
//			if (type.equals("KingPawn"))  {preField.setText("KaP-");colorField.setText("2");}
//			if (type.equals("MarketIS"))  {preField.setText("MIS-");colorField.setText("2");}
			}
		}
	
	/** method to read a bunch of numbers to be associated with a specific game.
		This was first built to read individual payoffs for the VoterGame.
		*/
	private float[][] readRaggedArray(File fn) {
		Vector<float[]> raggarray= new Vector<float[]>();
		try {
			FileReader frdr= new FileReader(fn);
			System.err.print(" raggedArray reading: "+fn);
			BufferedReader rdr= new BufferedReader(frdr);
			String line= rdr.readLine(); 
			while(line.length()>0) {
				StringTokenizer st= new StringTokenizer(line);
				int i=0, size= st.countTokens();
				float[] nmbrs= new float[size];
				while (st.hasMoreTokens())
					nmbrs[i++]= Float.parseFloat(st.nextToken());
				raggarray.add(nmbrs);
				System.err.print(" "+nmbrs.length);
				line= rdr.readLine(); 
				}
		} catch(Exception e) { System.err.println(e); System.exit(99); }
		System.err.println(" found "+raggarray.size()+" lines");
		return (float[][])raggarray.toArray();
		}
	
	/** method to invoke to start the game building GUI and process.
		@param args an array of Strings, each holding the name of a GraphPack.
			Each GraphPack will be used to define a game with a similar name.
		*/
	public static void main(String[] args) { new GameBuilder(args); }
	
	} // EOClass GameBuilder
